from __future__ import print_function

from kivy.app import App
from kivy.lang import Builder
from kivy.properties import ObjectProperty, StringProperty,\
    NumericProperty, BooleanProperty, ListProperty
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.scrollview import ScrollView
from kivy.uix.button import Button
from kivy.clock import Clock

from goblinoid.services.login_service import remove_current_user

Builder.load_file('goblinoid/profile/profilepanel.kv')


class ProfilePanel(BoxLayout):
    profile_service = ObjectProperty()
    posts = NumericProperty(0)
    username = StringProperty()
    already_fetching = BooleanProperty(False)
    reached_end_of_outbox = BooleanProperty(False)
    outbox_activities = ListProperty([])
    child_modal = ObjectProperty()

    activity_scroll_view = ObjectProperty(None)
    activity_grid = ObjectProperty()

    def __init__(self, **kwargs):
        super(ProfilePanel, self).__init__(**kwargs)
        Clock.schedule_interval(self.ensure_scroll_y_trigger, 0.5)

    def on_profile_service(self, instance, profile_service):
        try:
            self.activity_grid.bind(minimum_height=self.activity_grid.setter(
                'height'))
            self.username = unicode(profile_service.get_username())
            self.init_posts()
        except KeyError, e:
            print('KeyError: {0}'.format(e))

    def init_posts(self):
        cached_posts = self.fetch_cached_posts()
        if len(cached_posts) == 0:
            self.profile_service.set_callback(self.add_activity_items)
            self.fetch_posts()
        else:
            self.add_activity_items(cached_posts)

    def fetch_cached_posts(self):
        return self.profile_service.fetch_cached_posts()

    def fetch_posts(self):
        if not self.reached_end_of_outbox:
            self.profile_service.fetch_posts(self.add_activity_items)

    def evaluate_prefetch(self, scroll_y):
        if self.posts != 0:
            if scroll_y < 1/(float(self.posts) ** (1.0/3)):
                self.fetch_posts()

    def add_activity_items(self, activities):
        if activities == 'end':
            self.reached_end_of_outbox = True
        elif activities == 'error':
            # NOTE: for now, treat the same as 'end'
            self.reached_end_of_outbox = True
        else:
            for activity in activities:
                activity_item = RecentActivityItem(
                    index=self.posts,
                    image_source=activity.obj.thumbnail.url,
                    profile_panel=self)
                self.activity_grid.add_widget(activity_item)
                self.posts += 1

    def ensure_scroll_y_trigger(self, instance):
        if self.activity_grid and self.activity_scroll_view is not None:
            if self.activity_grid.height <= self.activity_scroll_view.height:
                self.fetch_posts()

    def open_activity_at_index(self, index):
        activity = self.profile_service.get_activity_from_index(index)
        # NOTE: both of these calls to the app will eventually be injected into
        # this view
        App.get_running_app().pump_service.add_profiles_from_activity(activity)
        App.get_running_app().dispatch_event(
            'on_new_screen',
            name=activity.id,
            class_name='activity',
            activity_id=activity.id)


class ProfileFeed(ScrollView):

    user_height = NumericProperty(0)
    container_height = NumericProperty(0)

    def on_container_height(self, instance, height):
        if height != 0:
            self.scroll_y = 1 - self.user_height / height
        else:
            self.scroll_y = 1

    def on_scroll_y(self, instance, scroll_y):
        self.user_height = (1 - scroll_y) * self.container_height


class RecentActivityItem(BoxLayout, Button):
    # NOTE: using index for now since it is faster than a image_source
    # lookup. This method is less secure though, since there is no
    # guarantee that the index corresponds with the correct activity in
    # the profile_service
    index = NumericProperty()
    image_source = StringProperty()
    profile_panel = ObjectProperty()

    def open_activity(self):
        self.profile_panel.open_activity_at_index(self.index)


class ProfileHeader(BoxLayout):
    username = StringProperty()
    posts = NumericProperty(0)
    followers = NumericProperty(0)
    following = NumericProperty(0)

    def __init__(self, **kwargs):
        super(ProfileHeader, self).__init__(**kwargs)

    def on_username(self, instance, username):
        if username == App.get_running_app().pump_service.pump.me.username:
            self.ids.profile_stats.add_widget(LogOutButton())


class LogOutButton(Button):

    def log_out(self):
        print('logging out...')
        remove_current_user(App.get_running_app().pump_service.data_dir)
        App.get_running_app().open_view('login', True)
        App.get_running_app().pump_service.feed_data = []
